package com.gotokeep.keep.composition.demo.samples;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.TextureView;
import android.widget.TextView;

import com.gotokeep.keep.composition.demo.R;
import com.gotokeep.keep.composition.demo.internal.SpeedPlayThread;
import com.gotokeep.keep.composition.demo.internal.SpeedRenderThread;
import com.gotokeep.keep.composition.demo.renderer.SpeedRenderer;
import com.gotokeep.keep.composition.demo.source.SourceProvider;
import com.gotokeep.keep.composition.demo.widgets.ScalableTextureView;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class FastPlayActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener,
        SpeedRenderThread.RenderListener {
    private static final String TAG = FastPlayActivity.class.getSimpleName();
    private ScalableTextureView previewView;
    private TextView timeView;
    private long time = 0;
    private long timeUs = 0;
    private AtomicInteger frameCount = new AtomicInteger(0);
    private long frameCountTime = 0;
    private float fps = 0;

    private SpeedRenderThread composerThread = null;
    private SpeedRenderer renderer = null;
//    private SpeedPlayThread playThread = null;
    private AtomicBoolean shouldRender = new AtomicBoolean(true);
    private TimeRunnable timeRunnable = new TimeRunnable();

    private static final float speed = 3.0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fast_play);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 0);
        }
        timeView = findViewById(R.id.time);
        previewView = findViewById(R.id.preview_view);
        previewView.setSurfaceTextureListener(this);

        renderer = new SpeedRenderer(this);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.d(TAG, String.format("onSurfaceTextureAvailable: w: %d, h: %d", width, height));
        renderer.setViewport(width, height);
        composerThread = new SpeedRenderThread(SourceProvider.VIDEO_SRC[0], surface, renderer, shouldRender, speed);
        composerThread.setRenderListener(this);
//        playThread = new SpeedPlayThread(SourceProvider.VIDEO_SRC[0], shouldRender, speed);
        composerThread.start();
//        playThread.start();
        timeRunnable.startMs = SystemClock.elapsedRealtime();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        renderer.setViewport(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        shouldRender.set(false);
        composerThread = null;
        timeView.removeCallbacks(timeRunnable);
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    public void onVideoSizeChanged(int width, int height, int rotation) {
        if (rotation % 180 == 90) {
            int t = width;
            width = height;
            height = t;
        }
        renderer.setVideoSize(width, height);
        final int finalWidth = width;
        final int finalHeight = height;
        previewView.post(new Runnable() {
            @Override
            public void run() {
                previewView.setVideoSize(finalWidth, finalHeight, 0);
            }
        });
    }

    @Override
    public void onVideoEnd() {
        timeView.removeCallbacks(timeRunnable);
    }

    @Override
    public void onFrameTime(long timeUs) {
        this.timeUs = (long) (timeUs / speed);
        frameCount.incrementAndGet();
    }

    @Override
    public void onFirstFrameRendered() {
        timeRunnable.startMs = SystemClock.elapsedRealtime();
        timeView.post(timeRunnable);
    }

    private class TimeRunnable implements Runnable {
        long startMs;
        @Override
        public void run() {
            long time = SystemClock.elapsedRealtime() - startMs;
            long t = timeUs / 1000;
            if (time - frameCountTime > 1000) {
                frameCountTime = time;
                fps = frameCount.get();
                frameCount.set(0);
            }
            timeView.setText(String.format("00:00:%02d.%03d\n00:00:%02d.%03d\nfps=%.1f/s", time / 1000, time % 1000,
                    t / 1000, t % 1000, fps));
            timeView.postOnAnimation(this);
        }
    }
}
